/*
 * Emini Physics Engine Demo source 
 * by Alexander Adensamer
 * 
 * Copyright (c) 2010, Emini Physics - Alexander Adensamer
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or 
 * without modification, are permitted provided that the following 
 * conditions are met:
 * 
 *  * Redistributions of source code must retain the above 
 *    copyright notice, this list of conditions and the 
 *    following disclaimer.
 *  * Redistributions in binary form must reproduce the above 
 *    copyright notice, this list of conditions and the following 
 *    disclaimer in the documentation and/or other materials provided 
 *    with the distribution.
 *  * Neither the name of the Emini Physics nor the names of 
 *    its contributors may be used to endorse or promote products 
 *    derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
 * OF SUCH DAMAGE.
 */

package com.myapp.balltest.graphics;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
import at.emini.physics2D.Body;
import at.emini.physics2D.util.FXUtil;

public class SimulationView extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener
{
    protected GraphicsWorld world;
    
    private Bitmap backGroundImage = null;
    
    private Body viewBody = null;          //view centered around this body
    private boolean useX = false;
    private boolean useY = false;
      
    public SimulationView(Context context, GraphicsWorld world) 
    {
        super(context);
        this.world = world;
        
     // register our interest in hearing about changes to our surface
        SurfaceHolder holder = getHolder();
        holder.addCallback(this);
        
        setOnTouchListener(this);
    }
        
    public void setBackground(Bitmap background)
    {
        backGroundImage = background;
    }
    
    public void setViewBody(Body viewBody, boolean useX, boolean useY)
    {
        this.viewBody = viewBody;
        this.useX = useX;
        this.useY = useY;
    }
    
    public int getViewTranslateX()
    {
        return (useX && viewBody != null )? ((viewBody.positionFX().xFX >> FXUtil.DECIMAL) - getWidth() / 2) : 0;
    }
    
    public int getViewTranslateY()
    {
        return (useY && viewBody != null )? ((viewBody.positionFX().yFX >> FXUtil.DECIMAL) - getHeight() / 2) : 0;
    }
        
    public void resetWorld(GraphicsWorld world)
    {
        this.world = world;
    }
    
    public void tickWorld()
    {
        if (world != null)
        {
            world.tick();
            
            Canvas c = null;
            SurfaceHolder holder = getHolder();
            try {
                c = holder.lockCanvas(null);
                synchronized (holder) {
                    doDraw(c);
                }
            } finally {
                // do this in a finally so that if an exception is thrown
                // during the above, we don't leave the Surface in an
                // inconsistent state
                if (c != null) {
                    holder.unlockCanvasAndPost(c);
                }
            }
        }
    }
    
    protected void doDraw(Canvas canvas) 
    {
        if (world != null && canvas != null)
        {
            if (backGroundImage != null)
            {
                canvas.drawBitmap(backGroundImage, 0, 0, null);
            }
            
            world.draw(canvas, getViewTranslateX(), getViewTranslateY());            
        }
    }

    /* Callback invoked when the surface dimensions change. */
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        if (width > 0 && height > 0) 
        {
            if (backGroundImage != null)
            {
                backGroundImage = Bitmap.createScaledBitmap( backGroundImage, 
                    getWidth(),        // new width
                    getHeight(),       // new height
                    true);
            }            
        }
    }
    
    public boolean onTouch(View v, MotionEvent event)
    {
        int x = (int) (event.getX() + getViewTranslateX());
        int y = (int) (event.getY() + getViewTranslateY());

        Body b = world.findBodyAt( x * FXUtil.ONE_FX, y * FXUtil.ONE_FX);
        if (b != null)  //we found a body that was touched
        {
            //use the thread safe remove method here, as the touch event can happen any time
            return onTouchBody(b, event);
        }
        return false;
    }
    
    /*
     * Callback for touched bodies
     */
    public boolean onTouchBody(Body body, MotionEvent event)
    {
        return false;
    }

    /*
     * Callback invoked when the Surface has been created and is ready to be
     * used.
     */
    public void surfaceCreated(SurfaceHolder holder) 
    {       
    }

    /*
     * Callback invoked when the Surface has been destroyed and must no longer
     * be touched. WARNING: after this method returns, the Surface/Canvas must
     * never be touched again!
     */
    public void surfaceDestroyed(SurfaceHolder holder) 
    {   
    }
}
